home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
public
/
plan
/
src
/
cyccalc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
5KB
|
160 lines
/*
* Move the date of entries that have recycling information to the next
* trigger date.
*
* length_of_month(time) Return the # of days in the month
* <time> [#secs since 1/1/70] is in
* recycle_all(list, del, days) Calls recycle() for all entries
* in <list>, and optionally deletes
* obsolete (expired) entries.
* recycle(entry, date, ret) If <entry> cycles, return its next
* trigger time after or on <date>,
* and find out if it is now obsolete.
*/
#include <time.h>
#include <Xm/Xm.h>
#include "cal.h"
int recycle();
extern struct tm *time_to_tm();
extern time_t get_time();
extern struct config config; /* global configuration data */
/*
* return the number of seconds in the month that <time> falls into. This
* routine overwrites the static tm buffer.
*/
time_t length_of_month(time)
time_t time; /* some date in the month */
{
struct tm *tm; /* time to m/d/y conv */
tm = time_to_tm(time);
time -= (tm->tm_mday-1) * 86400;
tm->tm_mday = 1;
if (tm->tm_mon++ == 11) {
tm->tm_mon = 0;
tm->tm_year++;
}
return(tm_to_time(tm) - time);
}
/*
* scan the entire list and remove obsolete entries, and recycle repeating
* entries. This is called regularly. Return TRUE if something changed. If
* TRUE is returned, the caller must call draw_calendar() and
* update_all_listmenus().
*/
BOOL recycle_all(list, del, days)
struct list *list; /* list to scan */
BOOL del; /* auto-remove obolete? */
int days; /* if del, keep if age < days*/
{
int n; /* entry counter */
time_t now; /* current time */
time_t time; /* next trigger time */
BOOL chg = FALSE; /* TRUE if list was changed */
now = get_time();
for (n=0; n < list->nentries; n++)
switch(recycle(&list->entry[n], now, &time)) {
case 2:
if (del && now - time > days * 86400) {
delete_entry(list, n--);
chg = TRUE;
}
break;
case 1:
if (time > list->entry[n].time) {
list->entry[n].time = time;
resort_entry(list, n--);
chg = TRUE;
}
break;
}
if (chg)
rebuild_repeat_chain(list);
return(chg);
}
/*
* If the entry has recycling info, move it up to the next date it triggers.
* Searching for the next trigger date if multiple repeat restrictions are
* set is very messy, I am using a trial-and-error approach for now.
* Set *ret to the time the entry will trigger next after <date>, and return
*
* 0 if the entry didn't change and doesn't trigger,
* 1 if the entry is triggering on or after date; trigger time is in *ret,
* 2 if the entry has become obsolete (24 hours after last trigger time).
*/
recycle(entry, date, ret)
register struct entry *entry; /* entry to test */
time_t date; /* today (time is ignored) */
register time_t *ret; /* returned next trigger time*/
{
struct tm tm1; /* first trigger m/d/y ever */
struct tm tm; /* time to m/d/y h:m:s conv */
time_t day; /* <date> with no time info */
long eday; /* entry date with no time */
long end; /* don't search too far */
long every; /* period in days */
int mlen = 0; /* # of days in test month */
register long w = entry->rep_weekdays;
register long d = entry->rep_days;
register time_t l = entry->rep_last;
*ret = entry->time;
eday = *ret / 86400;
day = date / 86400;
end = date + 86400 * 32;
if (day < eday)
return(0);
if (l && *ret > l + 86400-1)
return(2);
if (!entry->rep_every && !entry->rep_yearly && !w && !d)
return(date < *ret || date - *ret < 86400 ? 0 : 2);
if (entry->rep_every && !((day - eday) % (entry->rep_every/86400))) {
*ret %= 86400;
*ret += date - date % 86400;
return(l && *ret > l + 86400-1 ? 2 : 1);
}
if (entry->rep_yearly)
tm1 = *time_to_tm(entry->time);
every = entry->rep_every && !entry->rep_yearly ?
entry->rep_every / 86400 : 1;
*ret += ((day - eday + every-1) / every) * every * 86400;
while (*ret < end) {
tm = *time_to_tm(*ret);
if (l && *ret > l + 86400-1)
return(2);
if (entry->rep_yearly && tm.tm_mon == tm1.tm_mon
&& tm.tm_mday == tm1.tm_mday)
return(1);
if (entry->rep_every && *ret > date + entry->rep_every + 86400)
return(0);
if ((d & 1) || (w & 0x2000))
mlen = length_of_month(*ret) / 86400;
if (w & 1 << tm.tm_wday) {
if (!(w & 0x3f00))
return(1);
if ((w & 0x0100 << (tm.tm_mday-1) / 7) ||
(w & 0x2000) && tm.tm_mday+7 > mlen)
return(1);
}
if ((d & 1 << tm.tm_mday) ||
(d & 1) && tm.tm_mday == mlen)
return(1);
*ret += every * 86400;
}
return(*ret >= date && *ret < date + 86400 ? 1 : 0);
}